/**
 * @asignatura: Procesadores de Lenguajes.
 * @autor:      Anthony Vittorio Russo Cabrera
 * @curso:      2012/2013
 * @práctica:   02 - Pseudo-Analizador Léxico
 * @descripción:
 * Práctica 2: Comenzando con Analizador Léxico
 * En la práctica de esta semana vamos a plantear el acercamiento a un 
 * analizador léxico. Objetivo: Construir un pseudo-analizador léxico que cumpla
 * con las siguientes tareas:
 *  1.- Detectar que un código JAVA se encuentran dentro del conjunto de 
 *  caracteres especificado en un fichero, este puede venir dado por un fichero
 *  de texto o por un XML.
 *  2.- Detectar que este código JAVA, las palabras reservadas que 
 *  especificaremos en un fichero, este puede venir dado por un fichero de texto
 *  o por un XML.
 *  3.- Detectar el conjunto de bloques y especificarlos en la salida de la
 *  práctica.
 *  4.- La práctica debe contener un test unitario para cada uno de las tareas
 *  mencionadas. Y debe ser compilada y ejecutada a través de un fichero ANT.
 *  5.- La práctica debe tener sus propios test de comprobación
 */
package pl.p02;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.regex.PatternSyntaxException;

import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.Elements;
import nu.xom.ParsingException;
import nu.xom.ValidityException;

public class Symbols {

  private FileReader file  = null;
  public String      regex = null; // Expresión regular del alfabeto.

  public Symbols(String pathFile) {
    try {
      file = new FileReader(pathFile);
      if (pathFile.matches(".*xml$")) {
        xmlReader();
      } else {
        txtReader();
      }// ifelse
      file.close();

    } catch (FileNotFoundException e) {
      System.err.println("ERROR->Symbols.Constructor.FileNotFoundException:");
      System.err.println("No se encuentra el fichero '" + pathFile + "'");
      e.printStackTrace();
    } catch (IOException e) {
      System.err.println("ERROR->Symbols.Constructor.IOException:");
      System.err.println("file.close()");
      e.printStackTrace();
    }// try-catch
  }// Constructor

  private void xmlReader() {
    regex = "[";
    try {
      // Construir el árbol DOM a partir del fichero xml
      Document doc = new Builder().build(file);
      // Obtener el elemento raíz del árbol
      Element root = doc.getRootElement();
      Elements children = root.getChildElements();
      for (int i = 0; i < children.size(); i++) {
        Element child = children.get(i);
        regex += child.getValue();
      }// for

    } catch (ValidityException e) {
      e.printStackTrace();
    } catch (ParsingException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } // try-catch
    regex += "]*";
  }// xmlReader

  private void txtReader() {
    try {
      regex = new BufferedReader(file).readLine();
    } catch (IOException e) {
      System.err.println("Symbols.txtReader.IOException->ERROR");
      System.err.println("No se puede leer el fichero");
      e.printStackTrace();
    }
  }// txtReader

  public void parse(String line) throws LexicalException {
    try {
      if (!line.matches(regex)) { // Existe un carácter inválido en esta línea.
        int no_line = LexicalException.file.no_line;
        int no_column = 0;
        String description = "Caracteres inválidos:\n";

        // Buscar caracteres inválidos.
        String[] list = line.split(regex);
        for (String symbol : list) {
          if (!symbol.equalsIgnoreCase("")) {// Ignorar cadenas vacías
            no_column = line.indexOf(symbol, no_column);
            description += "[" + no_line + "," + (no_column + 1) + "] = '"
                + symbol + "'\n";
          }// if
        }// for
        throw new LexicalException(description);
      }// if
    } catch (PatternSyntaxException e) {
      System.err.println("ERROR->Symbols.check.PatternSyntaxException");
      System.err.println("Formato de cjto. de caracteres reconocidos inválido");
      e.printStackTrace();
    }

  }// check

}// Symbols
